import {
  VuexModule,
  Module,
  Action,
  Mutation,
  getModule,
} from 'vuex-module-decorators';
import store from '@/store';
import { getMonth, getDate } from '@/utils/date';
import { localStorageSet } from '@/utils/localStorageUtil';
import { loaclDataMap } from '@/utils/loaclDataMap';
import { tcbAuth, tcbDB } from '@/tcb';
import { Toast } from 'vant';

// 定义账单类型收入Revenue/支出Expense
export enum BillType {
  Revenue,
  Expense,
}

// 定义账单更新类型
export enum updateType {
  Insert,
  Delete,
  Update,
}

// 定义账单数据接口类型
export interface IBillData {
  billId: number;
  billTagId: number;
  billAccountId: number;
  billType: BillType;
  createTime: number;
  amount: number;
}

export interface IBillSummaryDate {
  date: string;
  amount: number;
}

export interface IBillSummary {
  month: string;
  revenueSummary: number;
  expenseSummary: number;
  revenueBills: IBillSummaryDate[];
  expenseBills: IBillSummaryDate[];
}

export interface IBillState {
  bills: IBillData[];
  billSummary: IBillSummary[];
  isEidtBillStatus: boolean;
  isAddBillStatus: boolean;
  currentEditBillId: number;
}

@Module({ dynamic: true, store, name: 'bill' })
class Bill extends VuexModule implements IBillState {
  public isEidtBillStatus: boolean = false;
  public isAddBillStatus: boolean = false;
  public currentEditBillId: number = 0;
  public billSummary: IBillSummary[] = [];
  public bills: IBillData[] = [];

  @Mutation
  public resetBills(bills: IBillData[]) {
    this.bills = bills;
  }
  @Mutation
  public toggleIsEditBillStatus(newEidtBillStatus: boolean) {
    this.isEidtBillStatus = newEidtBillStatus;
  }
  @Mutation
  public toggleIsAddBillStatus(newAddBillStatus: boolean) {
    this.isAddBillStatus = newAddBillStatus;
  }
  @Mutation
  public setCurrentEditBill(billId: number) {
    this.currentEditBillId = billId;
  }
  // 更新账单汇总数据
  @Mutation
  public updateBillSummary() {
    this.billSummary = [];
    this.bills.forEach((bill) => {
      const isRevenueBill = bill.billType === BillType.Revenue;
      const currentBillMonth = getMonth(new Date(bill.createTime));
      const currentBillDay = getDate(new Date(bill.createTime));
      const monthlyBillIndex = this.billSummary.findIndex((item) => {
        return item.month === currentBillMonth;
      });
      const billOptions = {
        date: currentBillDay,
        amount: bill.amount,
      };
      // 判断当前账单对应月份是否存在
      if (monthlyBillIndex !== -1) {
        const currentSummaryMonth = this.billSummary[monthlyBillIndex];
        if (isRevenueBill) {
          const dayBillIndex = currentSummaryMonth.revenueBills.findIndex((item) => {
            return item.date === currentBillDay;
          });
          if (dayBillIndex !== -1) {
            currentSummaryMonth.revenueBills[dayBillIndex].amount += bill.amount;
          } else {
            currentSummaryMonth.revenueBills.push(billOptions);
          }
          currentSummaryMonth.revenueSummary += bill.amount;
        } else {
          const dayBillIndex = currentSummaryMonth.expenseBills.findIndex((item) => {
            return item.date === currentBillDay;
          });
          if (dayBillIndex !== -1) {
            currentSummaryMonth.expenseBills[dayBillIndex].amount += bill.amount;
          } else {
            currentSummaryMonth.expenseBills.push(billOptions);
          }
          currentSummaryMonth.expenseSummary += bill.amount;
        }
      } else {
        this.billSummary.push({
          month: currentBillMonth,
          revenueSummary: isRevenueBill ? bill.amount : 0,
          expenseSummary: !isRevenueBill ? bill.amount : 0,
          revenueBills: isRevenueBill ? [billOptions] : [],
          expenseBills: !isRevenueBill ? [billOptions] : [],
        });
      }
    });
  }
  @Mutation
  public updateBillData(updateData: { type: updateType, billData: IBillData }) {
    if (updateData.type === updateType.Insert) {
      this.bills.unshift(updateData.billData);
    } else {
      const billIndex = this.bills.findIndex((item) => {
        return item.billId === updateData.billData.billId;
      });
      if (updateData.type === updateType.Delete) {
        this.bills.splice(billIndex, 1);
      } else {
        this.bills.splice(billIndex, 1, updateData.billData);
      }
    }
  }
  @Mutation
  public async updateBillStorage() {
    localStorageSet(loaclDataMap.bills, this.bills);
  }
  @Mutation
  public billSort() {
    this.bills.sort((a, b) => {
      return b.createTime - a.createTime;
    });
  }

  @Action
  public async updateBill(updateData: { type: updateType, billData: IBillData }) {
    // 这个模块里引用UserModule会报错，原因不明
    this.updateBillData(updateData);
    this.updateBillSummary();
    this.setCurrentEditBill(0);
    this.billSort();
    if (!store.state.user.isLogin) {
      this.updateBillStorage();
    } else {
      this.updateBillTcbStorage(updateData);
    }
  }
  @Action
  public async updateBillTcbStorage(updateData: { type: updateType, billData: IBillData }) {
    const userID = store.state.user.userID;
    switch (updateData.type) {
      case updateType.Insert:
        this.addBill({userID, billData: updateData.billData});
        break;
      case updateType.Update:
        this.editBill({userID, billData: updateData.billData});
        break;
      case updateType.Delete:
        this.removeBill({userID, billData: updateData.billData});
        break;
    }
  }
  @Action
  public async getBills(userID: string) {
    tcbDB.collection('bill_details').where({
      userID,
    }).get().then((res) => {
      // 返回的数据带有以下3个属性，遍历去掉，再赋值给本地数据
      res.data.forEach((item) => {
        delete item.userID;
        delete item._openid;
        delete item._id;
      });
      this.resetBills(res.data);
      this.billSort();
      this.updateBillSummary();
    }).catch(() => {
      Toast.fail('获取用户账单失败');
    });
  }
  @Action
  public async addBill(billOptions: { userID: string, billData: IBillData }) {
    tcbDB.collection('bill_details').add({userID: billOptions.userID, ...billOptions.billData}).catch(() => {
      Toast.fail('添加账单失败');
    });
  }
  @Action
  public async editBill(billOptions: { userID: string, billData: IBillData }) {
    const billId = billOptions.billData.billId;
    tcbDB.collection('bill_details').where({
      billId,
    }).update({ userID: billOptions.userID, ...billOptions.billData }).catch(() => {
      Toast.fail('编辑失败');
    });
  }
  @Action
  public async removeBill(billOptions: { userID: string, billData: IBillData }) {
    const billId = billOptions.billData.billId;
    tcbDB.collection('bill_details').where({
      billId,
    }).remove().catch(() => {
      Toast.fail('删除失败');
    });
  }
}

export const BillModule = getModule(Bill);
